package cool.doudou.doudada.cipher.algorithm.sm;

import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECFieldElement;
import org.bouncycastle.math.ec.ECPoint;

import java.math.BigInteger;
import java.security.SecureRandom;

/**
 * Sm2
 *
 * @author jiangcs
 * @since 2022/08/31
 */
public class Sm2 {
    // 国密参数
    public static String[] eccParam = {
            "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF",
            "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC",
            "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93",
            "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123",
            "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7",
            "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"
    };

    public static Sm2 Instance() {
        return new Sm2();
    }

    /**
     * 素数p
     */
    public final BigInteger eccP;
    /**
     * 系数a
     */
    public final BigInteger eccA;
    /**
     * 系数b
     */
    public final BigInteger eccB;
    /**
     * 基点G, G=(xg,yg),其介记为n
     */
    public final BigInteger eccN;
    /**
     * 坐标x
     */
    public final BigInteger eccGx;
    /**
     * 坐标y
     */
    public final BigInteger eccGy;
    public final ECCurve eccCurve;
    public final ECPoint eccPointG;
    public final ECDomainParameters eccBcSpec;
    public final ECKeyPairGenerator eccKeyPairGenerator;
    public final ECFieldElement ecFieldElementGx;
    public final ECFieldElement ecFieldElementGy;

    public Sm2() {
        this.eccP = new BigInteger(eccParam[0], 16);
        this.eccA = new BigInteger(eccParam[1], 16);
        this.eccB = new BigInteger(eccParam[2], 16);
        this.eccN = new BigInteger(eccParam[3], 16);
        this.eccGx = new BigInteger(eccParam[4], 16);
        this.eccGy = new BigInteger(eccParam[5], 16);

        this.ecFieldElementGx = new ECFieldElement.Fp(this.eccP, this.eccGx);
        this.ecFieldElementGy = new ECFieldElement.Fp(this.eccP, this.eccGy);

        this.eccCurve = new ECCurve.Fp(this.eccP, this.eccA, this.eccB);
        this.eccPointG = new ECPoint.Fp(this.eccCurve, this.ecFieldElementGx, this.ecFieldElementGy);

        this.eccBcSpec = new ECDomainParameters(this.eccCurve, this.eccPointG, this.eccN);

        ECKeyGenerationParameters ecKeyGenerationParameters = new ECKeyGenerationParameters(this.eccBcSpec, new SecureRandom());

        this.eccKeyPairGenerator = new ECKeyPairGenerator();
        this.eccKeyPairGenerator.init(ecKeyGenerationParameters);
    }
}
